//  这句话用来编程时自动提示，运行时需要注释掉！
//import * as BABYLON from '@babylonjs/core';

var canvas = document.getElementById("renderCanvas");

var startRenderLoop = function (engine, canvas) {
  engine.runRenderLoop(function () {
    if (sceneToRender && sceneToRender.activeCamera) {
      sceneToRender.render();
    }
  });
};

var engine = null;
var scene = null;
var sceneToRender = null;
var createDefaultEngine = function () {
  return new BABYLON.Engine(canvas, true, {
    preserveDrawingBuffer: true,
    stencil: true,
    disableWebGL2Support: false,
  });
};


//  创建场景（相关代码都在此处）
var createScene = function () {
  // This creates a basic Babylon Scene object (non-mesh)
  var scene = new BABYLON.Scene(engine);

  //  创建相机
  var camera = new BABYLON.ArcRotateCamera("camera", Math.PI / 2, 1.0, 10, BABYLON.Vector3.Zero());
  camera.attachControl(canvas, true);

  //  创建灯光
  var light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(1, 1, 0));

  //  显示坐标轴
  showAxis(6, scene);

  //  创建车的轮廓
  const outline = [
    new BABYLON.Vector3(-0.3, 0, -0.1),
    new BABYLON.Vector3(0.2, 0, -0.1)
  ]
  for (let i = 0; i < 20; i++) {
    outline.push(new BABYLON.Vector3(0.2 * Math.cos(i * Math.PI / 40), 0, 0.2 * Math.sin(i * Math.PI / 40) - 0.1));
  }
  outline.push(new BABYLON.Vector3(0, 0, 0.1));
  outline.push(new BABYLON.Vector3(-0.3, 0, 0.1));

  //car face UVs(0:top, 1:拉伸的地方, 2:bottom)
  const faceUV = [];
  faceUV[0] = new BABYLON.Vector4(0, 0.5, 0.38, 1);
  faceUV[1] = new BABYLON.Vector4(0, 0, 1, 0.5);
  faceUV[2] = new BABYLON.Vector4(0.38, 1, 0, 0.5);

  //car material
  const carMat = new BABYLON.StandardMaterial("carMat");
  carMat.diffuseTexture = new BABYLON.Texture("https://assets.babylonjs.com/environments/car.png");

  //  根据轮廓创建车
  const car = BABYLON.MeshBuilder.ExtrudePolygon("car", { shape: outline, depth: 0.2, faceUV: faceUV, wrap: true});
  car.material = carMat;

  //  车轮的UV（0:bottom, 1:拉伸的地方, 2:top）
  const wheelUV = [];
  wheelUV[0] = new BABYLON.Vector4(0, 0, 1, 1);
  wheelUV[1] = new BABYLON.Vector4(0, 0.5, 0.01, 0.51);
  wheelUV[2] = new BABYLON.Vector4(0, 0, 1, 1);
  const wheelMat = new BABYLON.StandardMaterial("wheelMat");
  wheelMat.diffuseTexture = new BABYLON.Texture("https://assets.babylonjs.com/environments/wheel.png");

  //  创建轮子
  const wheelRB = BABYLON.MeshBuilder.CreateCylinder("wheelRB", { diameter: 0.125, height: 0.05, faceUV: wheelUV});
  wheelRB.material = wheelMat;
  wheelRB.parent = car;
  wheelRB.position = new BABYLON.Vector3(-0.2, 0.035, -0.1);
  //  克隆轮子
  const wheelRF = wheelRB.clone("wheelRF");
  wheelRF.position.x = 0.1;
  const wheelLB = wheelRB.clone("wheelLB");
  wheelLB.position.y = -0.2 - 0.035;
  const wheelLF = wheelRF.clone("wheelLF");
  wheelLF.position.y = -0.2 - 0.035;

  //  轮子动画
  const animWheel = new BABYLON.Animation("animWheel", "rotation.y", 30, BABYLON.Animation.ANIMATIONTYPE_FLOAT, BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE);
  animWheel.setKeys([
    { frame: 0, value: 0 },
    { frame: 30, value: Math.PI }
  ]);
  wheelRB.animations.push(animWheel);
  wheelRF.animations.push(animWheel);
  wheelLB.animations.push(animWheel);
  wheelLF.animations.push(animWheel);

  scene.beginAnimation(wheelRB, 0, 30, true);
  scene.beginAnimation(wheelRF, 0, 30, true);
  scene.beginAnimation(wheelLB, 0, 30, true);
  scene.beginAnimation(wheelLF, 0, 30, true);

  return scene;
};


//  创建文字平面
const makeTextPlane = (text, color, size) => {
  const dynamicTexture = new BABYLON.DynamicTexture("dynamicTexture", 50, scene, true);
  dynamicTexture.hasAlpha = true;
  dynamicTexture.drawText(text, 5, 40, "bold 36px Arial", color, "transparent", true);

  const plane = BABYLON.MeshBuilder.CreatePlane("plane", { size: size, updatable: true }, scene);
  plane.material = new BABYLON.StandardMaterial("planeMat", scene);
  plane.material.backFaceCulling = false;
  plane.material.specularColor = new BABYLON.Color3(0, 0, 0);
  plane.material.diffuseTexture = dynamicTexture;
  return plane;
}

const showAxis = (length, scene) => {

  //  创建坐标轴x
  const xAxis = BABYLON.MeshBuilder.CreateLines("xAxis",
    {
      points: [new BABYLON.Vector3(0, 0, 0), new BABYLON.Vector3(length, 0, 0),
      new BABYLON.Vector3(length * 0.95, 0.1, 0), new BABYLON.Vector3(length, 0, 0),
      new BABYLON.Vector3(length * 0.95, -0.1, 0)]
    }, scene);
  xAxis.color = new BABYLON.Color3(1, 0, 0);
  const xText = makeTextPlane("X", "red", length / 10.0);
  xText.position = new BABYLON.Vector3(length * 0.95, -0.05 * length, 0);

  //  创建坐标轴y
  const yAxis = BABYLON.MeshBuilder.CreateLines("yAxis",
    {
      points: [new BABYLON.Vector3(0, 0, 0), new BABYLON.Vector3(0, length, 0),
      new BABYLON.Vector3(-0.1, length * 0.95, 0), new BABYLON.Vector3(0, length, 0),
      new BABYLON.Vector3(0.1, length * 0.95, 0)]
    }, scene);
  yAxis.color = new BABYLON.Color3(0, 1, 0);
  const yText = makeTextPlane("Y", "green", length / 10.0);
  yText.position = new BABYLON.Vector3(0.05 * length, length * 0.95, 0);

  //  创建坐标轴z
  const zAxis = BABYLON.MeshBuilder.CreateLines("zAxis",
    {
      points: [new BABYLON.Vector3(0, 0, 0), new BABYLON.Vector3(0, 0, length),
      new BABYLON.Vector3(0, -0.1, length * 0.95), new BABYLON.Vector3(0, 0, length),
      new BABYLON.Vector3(0, 0.1, length * 0.95)]
    }, scene);
  zAxis.color = new BABYLON.Color3(0, 0, 1);
  const zText = makeTextPlane("Z", "blue", length / 10.0);
  zText.position = new BABYLON.Vector3(0.05 * length, 0.05 * length, length * 0.95);
}


const localAxis = (length, scene) => {

  //  创建坐标轴x
  const xAxis = BABYLON.MeshBuilder.CreateLines("local_xAxis",
    {
      points: [new BABYLON.Vector3(0, 0, 0), new BABYLON.Vector3(length, 0, 0),
      new BABYLON.Vector3(length * 0.95, 0.1, 0), new BABYLON.Vector3(length, 0, 0),
      new BABYLON.Vector3(length * 0.95, -0.1, 0)]
    }, scene);
  xAxis.color = new BABYLON.Color3(1, 0, 0);

  //  创建坐标轴y
  const yAxis = BABYLON.MeshBuilder.CreateLines("local_yAxis",
    {
      points: [new BABYLON.Vector3(0, 0, 0), new BABYLON.Vector3(0, length, 0),
      new BABYLON.Vector3(-0.1, length * 0.95, 0), new BABYLON.Vector3(0, length, 0),
      new BABYLON.Vector3(0.1, length * 0.95, 0)]
    }, scene);
  yAxis.color = new BABYLON.Color3(0, 1, 0);

  //  创建坐标轴z
  const zAxis = BABYLON.MeshBuilder.CreateLines("local_zAxis",
    {
      points: [new BABYLON.Vector3(0, 0, 0), new BABYLON.Vector3(0, 0, length),
      new BABYLON.Vector3(0, -0.1, length * 0.95), new BABYLON.Vector3(0, 0, length),
      new BABYLON.Vector3(0, 0.1, length * 0.95)]
    }, scene);
  zAxis.color = new BABYLON.Color3(0, 0, 1);

  //  合并坐标轴(TransformNode不渲染)
  const local_origion = new BABYLON.TransformNode("local_origion", scene);

  local_origion.addChild(xAxis);
  local_origion.addChild(yAxis);
  local_origion.addChild(zAxis);

  return local_origion;
}



//================================================

window.initFunction = async function () {
  var asyncEngineCreation = async function () {
    try {
      return createDefaultEngine();
    } catch (e) {
      console.log(
        "the available createEngine function failed. Creating the default engine instead"
      );
      return createDefaultEngine();
    }
  };

  window.engine = await asyncEngineCreation();
  if (!engine) throw "engine should not be null.";
  startRenderLoop(engine, canvas);
  window.scene = createScene();
};
initFunction().then(() => {
  sceneToRender = scene;
});

// Resize
window.addEventListener("resize", function () {
  engine.resize();
});